/*
 *  Copyright (C) 2011 glauco
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.balisunrise.swing.components.documents;

import java.text.DecimalFormatSymbols;

/**
 * Filtar caracteres para formar numeros, podendo ser números inteiros
 * ou decimais, não negativos ou positivos e negativos.
 *
 * @author glauco
 */
public class NumericFilter implements DocumentFilter{

    /**
     * Consistencia para permitir numeros negativos.
     * Quando este attributo tem o valor falso, não é permitido números
     * negativos.
     */
    boolean negatives;

    /**
     * Consistencia para permitir numeros decimal.
     * Quando este attributo tem o valor falso, não é permitido números
     * decimais.
     */
    boolean decimal;

    /**
     * Caracter separador de milhar
     */
    public final static char separadorMilhar =
            DecimalFormatSymbols.getInstance().getGroupingSeparator();

    /**
     * Caracter separador decimal.
     */
    public final static char separadorDecimal =
            DecimalFormatSymbols.getInstance().getDecimalSeparator();

    /**
     * Contrutor padrão.
     * @param negatives se aceita numeros negativos.
     * @param decimal se aceita numeros decimal.
     */
    public NumericFilter(boolean negatives, boolean decimal) {
        this.negatives = negatives;
        this.decimal = decimal;
    }

    /**
     * Verificador de números.
     * @param actualValue Valor atual do documento.
     * @param offSet posição inicial para inserir o segmento de string.
     * @param adding segmento de string que será inserido no documento.
     * @return É retornado o valor do segmento de string a ser
     * inserido no documento, ou null caso o valor não seja válido.
     */
    @Override
    public String beforeInsert(String actualValue, int offSet, String adding) {

        boolean notHasDecimal =
                ! actualValue.contains(String.valueOf(separadorDecimal));

        // permite apenas digitos
        for (char c : adding.toCharArray()) {

            // Se for um digito, passou.
            if(Character.isDigit(c))
                continue;

            // se for um separador de milhar e o documento ter tamanho
            // para usa-lo, passou.
            if (c == separadorMilhar)
                continue;

            // se for separador decimal e o numero for decimal, passou.
            if (c == separadorDecimal && decimal && notHasDecimal){
                notHasDecimal = false;
                continue;
            }
                

            // se aceita negativos, reprovado
            // ou
            // se não é digito, separador de milhar ou decimal,
            //e não for sinal de negativo, reprovado
            if( !negatives || c != '-')
                return null;
        }

        return adding;
    }

}
